package com.snow.jpa;

import com.snow.conditions.ConditionType;
import com.snow.conditions.LinkType;
import com.snow.conditions.QueryCondition;
import com.snow.conditions.QueryOrder;
import com.snow.exception.CommonRuntimeException;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 查询条件构造器
 *
 * @author by 13119
 */
@Slf4j
@Getter
@Setter
@Accessors(chain = true)
public class LambdaQueryBuilder<E extends IBaseEntity<ID>, ID> {

    List<QueryCondition> conditions = new ArrayList<>();
    BaseRepository<E, ID> baseRepository;
    QueryCondition rootQueryCondition;
    List<QueryOrder> orders = new ArrayList<>();

    public static void disableTenantFilter() {
        RequestContextHolder.currentRequestAttributes()
                .setAttribute("disableTenantFilter", true, RequestAttributes.SCOPE_REQUEST);
    }

    public static void disableDeptDatascopeFilter() {
        if (RequestContextHolder.getRequestAttributes() == null) {
            log.debug("当前环境非 web环境，将使用线程变量");
        } else {
            RequestContextHolder.currentRequestAttributes()
                    .setAttribute("disableDeptDataScope", true, RequestAttributes.SCOPE_REQUEST);
        }
    }

    /**
     * 查询符合条件的所有
     */
    public List<E> findAll() {
        return this.baseRepository.findAll(this.baseRepository.toSpec(this.rootQueryCondition));
    }

    public List<E> findAll(boolean enableTenantFilter) {
        return this.baseRepository.findAll(this.baseRepository.toSpec(this.rootQueryCondition, enableTenantFilter));
    }

    public E findBy(String column, Object value) {
        return this.equal(column, value).one();
    }

    public static boolean getEnableTenantFilter() {
        try {
            RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
            Object attribute = requestAttributes.getAttribute("disableTenantFilter", RequestAttributes.SCOPE_REQUEST);
            // attribute == null 表示没有设置 则默认启用租户过滤
            return attribute == null || !(Boolean) attribute;
        } catch (IllegalStateException e) {
            return true; // 默认启用租户过滤
        }
    }

    public static boolean getEnableDeptDataScope() {
        try {
            RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
            Object attribute = requestAttributes.getAttribute("disableDeptDataScope", RequestAttributes.SCOPE_REQUEST);
            // attribute == null 表示没有设置 则默认启用部门数据范围过滤
            return attribute == null || !(Boolean) attribute;
        } catch (IllegalStateException e) {
            return true; // 默认启用部门数据范围过滤
        }
    }


    public List<E> findAllBy(String column, Object value, boolean enableTenantFilter) {
        return equal(column, value).findAll(enableTenantFilter);
    }

    public List<E> findAllBy(String column, Object value) {
        return equal(column, value).findAll();
    }

    /**
     * 统计符合条件的数量
     */
    public long count() {
        return this.baseRepository.count(this.baseRepository.toSpec(this.rootQueryCondition));
    }

    /**
     * 分页获取
     * page 必须 从1 开始
     */
    public Page<E> page(Integer page, Integer size) {
        if (page < 1) {
            throw new CommonRuntimeException("page页码值必须从1开始");
        }
        return this.baseRepository.findAll(this.baseRepository.toSpec(this.rootQueryCondition), PageRequest.of(page - 1, size));
    }

    /**
     * 获取前size条数据
     */
    public List<E> top(Integer size) {
        return this.baseRepository.findAll(this.baseRepository.toSpec(this.rootQueryCondition), PageRequest.of(0, size)).getContent();
    }

    /**
     * 符合条件的是否存在
     */
    public boolean exists() {
        return this.baseRepository.exists(this.baseRepository.toSpec(this.rootQueryCondition));
    }

    public void delete() {
        List<ID> ids = findAll().stream().map(E::getId).collect(Collectors.toList());
        this.baseRepository.deleteAllByIdInBatch(ids);
    }

    /**
     * 获取一个对象
     */
    public E one() {
        Optional<E> optionalE = this.baseRepository.findOne(this.baseRepository.toSpec(this.rootQueryCondition));
        return optionalE.orElse(null);
    }

    public LambdaQueryBuilder(BaseRepository<E, ID> baseRepository) {
        this.rootQueryCondition = new QueryCondition(LinkType.AND, conditions);
        this.baseRepository = baseRepository;
    }

    /**
     * 等于
     */
    public LambdaQueryBuilder<E, ID> equal(String column, Object value) {
        conditions.add(new QueryCondition(column, value, ConditionType.equal));
        return this;
    }

    /**
     * 不等于
     */
    public LambdaQueryBuilder<E, ID> notEqual(String column, Object value) {
        conditions.add(new QueryCondition(column, value, ConditionType.notEqual));
        return this;
    }

    /**
     * 大于
     */
    public LambdaQueryBuilder<E, ID> greaterThan(String column, Object value) {
        conditions.add(new QueryCondition(column, value, ConditionType.greaterThan));
        return this;
    }


    public LambdaQueryBuilder<E, ID> greaterThanOrEqual(String column, Object value) {
        conditions.add(new QueryCondition(column, value, ConditionType.greaterThanOrEqual));
        return this;
    }


    public LambdaQueryBuilder<E, ID> lessThan(String column, Object value) {
        conditions.add(new QueryCondition(column, value, ConditionType.lessThan));
        return this;
    }

    public LambdaQueryBuilder<E, ID> lessThanOrEqual(String column, Object value) {
        conditions.add(new QueryCondition(column, value, ConditionType.lessThanOrEqual));
        return this;
    }

    public LambdaQueryBuilder<E, ID> between(String column, Date start, Date end) {
        conditions.add(new QueryCondition(column, start, ConditionType.greaterThanOrEqual));
        conditions.add(new QueryCondition(column, end, ConditionType.lessThanOrEqual));
        return this;
    }

    /**
     * 左模糊查询
     */
    public LambdaQueryBuilder<E, ID> like(String column, Object value) {
        conditions.add(new QueryCondition(column, value, ConditionType.like));
        return this;
    }

    /**
     * 左模糊查询
     */
    public LambdaQueryBuilder<E, ID> likeLeft(String column, Object value) {
        conditions.add(new QueryCondition(column, value, ConditionType.likeLeft));
        return this;
    }

    /**
     * 右模糊查询
     */
    public LambdaQueryBuilder<E, ID> likeRight(String column, Object value) {
        conditions.add(new QueryCondition(column, value, ConditionType.likeRight));
        return this;
    }

    /**
     * 包含
     */
    public LambdaQueryBuilder<E, ID> in(String column, Object... value) {
        conditions.add(new QueryCondition(column, value, ConditionType.in));
        return this;
    }

    /**
     * 正序排列
     */
    public LambdaQueryBuilder<E, ID> asc(String column) {
        this.orders.add(QueryOrder.asc(column));
        return this;
    }

    /**
     * 倒序排
     */
    public LambdaQueryBuilder<E, ID> desc(String column) {
        this.orders.add(QueryOrder.desc(column));
        return this;
    }

    public LambdaQueryBuilder<E, ID> disTenantFilter() {
        disableTenantFilter();
        return this;
    }

    public LambdaQueryBuilder<E, ID> disDeptDataScopeFilter() {
        disableDeptDatascopeFilter();
        return this;
    }


}
